﻿using LibreHardwareMonitor.Hardware;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace XinLife.Core.Helper
{
    public static class HardwareMonitor
    {
        private static Computer? computer;
        private static dynamic r = new System.Dynamic.ExpandoObject();

        static HardwareMonitor()
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                computer = new Computer()
                {
                    IsCpuEnabled = true,
                    IsMemoryEnabled = true,
                };
                computer.Open();
                computer.Accept(new UpdateVisitor());
            }
        }

        public static object GetCPUUsage()
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                return GetWindowsData();
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                return GetLinuxData();
            }
            else
            {
                return new { cpu = 0, memory = 0 };
            }
        }
        public static object GetWindowsData()
        {
            r.cpu = 0;
            r.memory = 0;

            foreach (var hardware in computer.Hardware)
            {
                if (hardware.HardwareType == HardwareType.Cpu)
                {
                    hardware.Update();
                    foreach (var sensor in hardware.Sensors)
                    {
                        if (sensor.SensorType == SensorType.Load && sensor.Name == "CPU Total")
                        {
                            r.cpu = (sensor.Value ?? 0).ToString("F2");
                        }
                    }
                }
                else if (hardware.HardwareType == HardwareType.Memory)
                {
                    hardware.Update();
                    foreach (var sensor in hardware.Sensors)
                    {
                        if (sensor.SensorType == SensorType.Load && sensor.Name == "Memory")
                        {
                            r.memory = (sensor.Value ?? 0.0f).ToString("F2");
                        }
                    }
                }
            }
            return r;
        }


        private static object GetLinuxData()
        {
            r.cpu = 0;
            r.memory = 0;

            string[]? cpuInfo = File.ReadAllLines("/proc/stat")
                                    .Where(line => line.StartsWith("cpu "))
                                    .Select(line => line.Split(' ', StringSplitOptions.RemoveEmptyEntries))
                                    .FirstOrDefault();

            if (cpuInfo != null && cpuInfo.Length >= 8)
            {
                double totalCpuTime = cpuInfo.Skip(1).Select(long.Parse).Sum();
                double idleCpuTime = double.Parse(cpuInfo[4]);

                r.cpu = (100 - idleCpuTime / totalCpuTime * 100).ToString("F2");
            }

            string memInfoFile = "/proc/meminfo";
            string[] lines = File.ReadAllLines(memInfoFile);

            // 查找 "MemTotal" 和 "MemAvailable" 行
            long memTotal = ParseMemInfoValue(lines.Where(line => line.StartsWith("MemTotal:")).LastOrDefault());
            long memAvailable = ParseMemInfoValue(lines.Where(line => line.StartsWith("MemAvailable:")).LastOrDefault());

            // 计算内存使用率
            double memoryUsage = (1 - (double)memAvailable / memTotal) * 100;

            r.memory = memoryUsage.ToString("F2");
            return r;
        }

        private static long ParseMemInfoValue(string line)
        {
            // 从行中提取数字部分
            string valueString = line.Split(':')[1].Trim();
            string numberString = valueString.Split(' ')[0];

            // 解析数字
            if (long.TryParse(numberString, out long value))
            {
                return value;
            }
            return 0;
        }
    }

    public class UpdateVisitor : IVisitor
    {
        public void VisitComputer(IComputer computer)
        {
            computer.Traverse(this);
        }
        public void VisitHardware(IHardware hardware)
        {
            hardware.Update();
            foreach (IHardware subHardware in hardware.SubHardware) subHardware.Accept(this);
        }
        public void VisitSensor(ISensor sensor) { }
        public void VisitParameter(IParameter parameter) { }
    }

}
